package com.ly.wxstore.service.weixin;

import java.util.Calendar;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springside.modules.mapper.JsonMapper;

import com.ly.wxstore.entity.weixin.WeixinJsapiTicket;
import com.ly.wxstore.entity.weixin.WeixinJsapiTicketLog;
import com.ly.wxstore.exception.ServerException;
import com.ly.wxstore.repository.weixin.WeixinJsapiTicketDao;
import com.ly.wxstore.repository.weixin.WeixinJsapiTicketLogDao;
import com.ly.wxstore.rest.dto.JsapiTicketDto;
import com.ly.wxstore.utils.HttpUtil;

/**
 * 
 * 
 * @author Peter
 */
// Spring Service Bean的标识.
@Component
public class WeixinJsapiTicketService {

	private static Logger logger = LoggerFactory.getLogger(WeixinJsapiTicketService.class);

	private JsonMapper mapper = JsonMapper.nonDefaultMapper();

	@Autowired
	private WeixinJsapiTicketDao weixinJsapiTicketDao;

	@Autowired
	private WeixinConf weixinConf;

	@Autowired
	private WeixinJsapiTicketLogDao weixinJsapiTicketLogDao;

	@Autowired
	private WeixinAccessTokenService weixinAccessTokenService;

	// ----------------------------------------------------------------------------------------------
	public String getJsapiTicket() throws ServerException {
		String jsapiTicket = "";
		logger.info("读取数据库中的accessToken");

		WeixinJsapiTicket ticket = weixinJsapiTicketDao.getById(weixinConf.getPublicId());
		if (ticket == null) {
			// 数据库中没有ticket信息，从微信服务器获取ticket
			logger.info("数据库中没有ticket信息，从微信服务器获取ticket");
			JsapiTicketDto dto = getTicketFromWeixinServer();
			ticket = dtoToEntity(dto);
			ticket.setWeixinPublicId(weixinConf.getPublicId());
			WeixinJsapiTicketLog ticketLog = dtoToJsapiTicketLog(dto);
			weixinJsapiTicketDao.save(ticket);
			weixinJsapiTicketLogDao.save(ticketLog);
		} else {
			// 判断是否过期
			if (isExpires(ticket)) {
				// 过期，重新获取ticket
				logger.info("过期，重新获取ticket");
				Long id = ticket.getId();
				JsapiTicketDto dto = getTicketFromWeixinServer();
				ticket = dtoToEntity(dto);
				WeixinJsapiTicketLog ticketLog = dtoToJsapiTicketLog(dto);

				ticket.setId(id);
				weixinJsapiTicketDao.update(ticket);
				weixinJsapiTicketLogDao.save(ticketLog);
			}
		}
		jsapiTicket = ticket.getJsapiTicket();
		return jsapiTicket;
	}

	private JsapiTicketDto getTicketFromWeixinServer() throws ServerException {
		String accessToken = weixinAccessTokenService.getAccessToken();

		// https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=NRyi9YnmjZU_VsTUSFNsOxp3GfY5ZexbnbZPMX0hAC7Zcdrn20_m7qFzHTcsaDf99g83W7K_uAwxuwyHtcrqJRlYps2FlBnNJQUauiznTdk&type=jsapi
		String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";

		// {"errcode":0,"errmsg":"ok","ticket":"bxLdikRXVbTPdHSM05e5u3tgwh7S8MpcDcXHS8MO__V-YjhJbpE7gnR72fmm77V2b_t_LGHFWKI-i2V4DZRWsg","expires_in":7200}
		String body = HttpUtil.httpGet(url);
		JsapiTicketDto bean = mapper.fromJson(body, JsapiTicketDto.class);
		if (bean.getErrcode().longValue() == 0L && "ok".equals(bean.getErrmsg())) {
			return bean;
		} else {
			throw new ServerException(bean.getErrcode().toString(), bean.getErrmsg());
		}

	}

	private WeixinJsapiTicket dtoToEntity(JsapiTicketDto dto) {
		WeixinJsapiTicket t = new WeixinJsapiTicket();
		t.setCreateDate(new Date());
		t.setUpdateDate(new Date());
		t.setExpiresIn(Long.valueOf(dto.getExpires_in()));
		t.setJsapiTicket(dto.getTicket());
		return t;
	}

	private WeixinJsapiTicketLog dtoToJsapiTicketLog(JsapiTicketDto dto) {
		WeixinJsapiTicketLog t = new WeixinJsapiTicketLog();
		t.setCreateDate(new Date());
		t.setExpiresIn(Long.valueOf(dto.getExpires_in()));
		t.setJsapiTicket(dto.getTicket());
		t.setErrcode(dto.getErrcode().toString());
		t.setErrmsg(dto.getErrmsg());
		t.setWeixinPublicId(weixinConf.getPublicId());

		return t;
	}

	/**
	 * 是否过期
	 * 
	 * @param ticket
	 * @return
	 */
	public boolean isExpires(WeixinJsapiTicket ticket) {
		boolean isExpires = false;

		Calendar sendedCal = Calendar.getInstance();//
		sendedCal.setTime(ticket.getUpdateDate());
		sendedCal.add(Calendar.SECOND, ticket.getExpiresIn().intValue() - 120);// 提前2分钟过期

		Calendar nowCal = Calendar.getInstance();
		nowCal.setTime(new Date());

		if (sendedCal.before(nowCal)) {
			isExpires = true;
		}

		return isExpires;
	}
}
